/*******************************************************************
 *   > File Name: mkv210_image.c
 *   > Author: fly
 *   > Mail: 1358326274@qq.com
 *   > Create Time: 2020年07月17日 星期五 00时13分47秒
 ******************************************************************/

/*-----------------------------------------------------------------
 *mkv210_image.c的作用:将USB启动时使用的BIN文件制作得到SD卡启动的
 *Image
 *计算文件校验和，添加16字节的文件头，将校验和写入文件头第8字节处
 *----------------------------------------------------------------*/
// 前16字节需要提前填充
/* egg:
 * bl1 header infomation for irom
 *
 * 0x0 - bl1 size
 * 0x4 - reserved (should be 0)
 * 0x8 - check sum
 * 0xc - reserved (should be 0)
 */
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include "debug.h"

#define BL1_MAX_SIZE        (16*1204)//16KB max size
#define BL1_SET_SIZE        (16*1024)
#define BL1_HEAD_SIZE       (16)//16byte

#define SD_FILE_NAME_HEAD   ""
#define SD_FILE_NAME_TAIL   ".sd.bin"
#define FILE_NAME_MAX_SIZE  (128)

int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        printf("Usage:"YELLOW"%s <src_file>"NONE"\n",argv[0]);return (-1);
    }

    FILE *fps, *fpd;
    fps = fopen(argv[1], "r");
    if(fps == NULL)
    {
        printf("fopen %s err: %s\n",argv[1],strerror(errno));
        return (-2);
    }

    //获取新的文件名
    //printf("%s\n", strrchr(argv[1], '.'));
    char file_name[FILE_NAME_MAX_SIZE] = {0};
    memcpy(file_name, argv[1], strlen(argv[1]));
    memcpy(strrchr(file_name, '.'), SD_FILE_NAME_TAIL, sizeof(SD_FILE_NAME_TAIL));
    //printf("%s\n", file_name);

    //创建新的文件
    char *BUF;
    fpd = fopen(file_name, "w");
    if(fpd == NULL)
    {
        printf("fopen %s err: %s\n",file_name,strerror(errno));
        return (-2);
    }
    
    BUF = (char *)malloc(BL1_HEAD_SIZE);
    if(BUF == NULL)
    {
        fclose(fps);fclose(fpd);
        printf("malloc BUF err: %s\n", strerror(errno));
        return (-3);
    }
    memset(BUF, 0, BL1_HEAD_SIZE);
    // BL1 Size
    *(unsigned int *)BUF = BL1_SET_SIZE;
    fwrite(BUF, 1, sizeof(unsigned int), fpd);
    // Reserved (should be 0)
    *(unsigned int *)BUF = 0x0;
    fwrite(BUF, 1, sizeof(unsigned int), fpd);
    // check sum, init set 0
    *(unsigned int *)BUF = 0x0;
    fwrite(BUF, 1, sizeof(unsigned int), fpd);
    // Reserved (should be 0)
    *(unsigned int *)BUF = 0x0;
    fwrite(BUF, 1, sizeof(unsigned int), fpd);

    int fileLen;
    fseek(fps, 0L, SEEK_END);   //定位到文件尾
    fileLen = ftell(fps);       //获取文件长度
    printf("%s size:"YELLOW"%d"NONE"bytes\n", argv[1], fileLen);
    fseek(fps, 0L, SEEK_SET);   //定位到文件头
    
    /* 获取需要计算校验的字节数 */
    /* Making checksum example code
     * for(count=0;count< dataLength;count+=1)
     * {
     *      buffer = (*(volatile u8*)(uBlAddr+count));
     *      checkSum = checkSum + buffer;
     * }
     * */
    unsigned int dataLen;
    unsigned int checkSum = 0;
    unsigned int count = 0;
    unsigned char byte[1];
    dataLen = (fileLen < (BL1_SET_SIZE - BL1_HEAD_SIZE))?fileLen:(BL1_SET_SIZE - BL1_HEAD_SIZE);
    for(count = 0; count < dataLen; count ++)
    {
           fread(&byte, sizeof(unsigned char), 1, fps);
           checkSum += byte[0];
           fwrite(&byte, sizeof(unsigned char), 1, fpd);
    }
    printf("checkSum: "GREEN"0X%08X"NONE" for "GREEN"%d"NONE"bytes\n", checkSum, count);
    if(fileLen<= (BL1_SET_SIZE - BL1_HEAD_SIZE)) 
    {
        /* 不够的字节数，填充零 */
        for(count = 0; count < (BL1_SET_SIZE - BL1_HEAD_SIZE - dataLen); count ++)
        {
            byte[0] = 0x0;
            fwrite(&byte, sizeof(unsigned char), 1, fpd);
        }
    }else{
        /* 将剩下不校验的字节数写到目标文件中 */
        for(count = 0; count < (fileLen - (BL1_SET_SIZE - BL1_HEAD_SIZE)); count ++)
        {
           fread(&byte, sizeof(unsigned char), 1, fps);
           fwrite(&byte, sizeof(unsigned char), 1, fpd);
        }
    }

    printf("create file:"GREEN"%s"NONE" for "GREEN"%ld"NONE"bytes\n", file_name, ftell(fpd));
    //定位到第8个字节处，写入校验和
    fseek(fpd, 8L, SEEK_SET);
    fwrite(&checkSum, sizeof(checkSum), 1, fpd);

    fclose(fps);
    fclose(fpd);
    free(BUF);

    return 0;
}
